import axios from "axios"
import * as crypto from "crypto"

export class CursorAccessTokenGetter {
  private cookieToken: string = ""

  /**
   * Base64URL 编码
   */
  private base64URLEncode(data: Uint8Array): string {
    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
    let result = ""
    const remainder = data.length % 3
    let i = 0

    for (; i < data.length - remainder; i += 3) {
      const a = data[i]
      const b = data[i + 1]
      const c = data[i + 2]

      result += chars[a >>> 2]
      result += chars[((a << 4) | (b >>> 4)) & 63]
      result += chars[((b << 2) | (c >>> 6)) & 63]
      result += chars[c & 63]
    }

    if (remainder === 1) {
      const a = data[i]
      result += chars[a >>> 2]
      result += chars[(a << 4) & 63]
    } else if (remainder === 2) {
      const a = data[i]
      const b = data[i + 1]
      result += chars[a >>> 2]
      result += chars[((a << 4) | (b >>> 4)) & 63]
      result += chars[(b << 2) & 63]
    }

    return result
  }

  /**
   * SHA256 哈希
   */
  private sha256(input: string): Uint8Array {
    const hash = crypto.createHash("sha256")
    hash.update(input)
    return new Uint8Array(hash.digest())
  }

  /**
   * 获取 AccessToken
   * @param cookieToken WorkOS Session Token
   * @returns {Promise<{accessToken: string, email: string}>}
   */
  async getAccessToken(cookieToken: string): Promise<{ accessToken: string; email?: string }> {
    try {
      console.log("=== CursorAccessTokenGetter.getAccessToken 开始 ===")
      console.log("WorkOS Token 长度:", cookieToken.length)

      // 保存 token
      this.cookieToken = cookieToken

      // 1. 生成参数
      const randomBytes = crypto.randomBytes(32)
      const verifier = this.base64URLEncode(new Uint8Array(randomBytes))
      const challenge = this.base64URLEncode(this.sha256(verifier))
      const uuid = crypto.randomUUID()

      console.log("📝 生成的参数:")
      console.log("  UUID:", uuid)
      console.log("  Verifier:", verifier.substring(0, 20) + "...")
      console.log("  Challenge:", challenge.substring(0, 20) + "...")

      // 2. 触发授权登录
      console.log("🔄 Step 1: 触发授权登录...")
      console.log("  请求 URL:", "https://cursor.com/api/auth/loginDeepCallbackControl")

      const loginResponse = await axios.post(
        "https://cursor.com/api/auth/loginDeepCallbackControl",
        {
          challenge: challenge,
          uuid: uuid
        },
        {
          headers: {
            "Content-Type": "application/json",
            Accept: "*/*",
            Origin: "https://cursor.com",
            Cookie: `WorkosCursorSessionToken=${cookieToken}`
          }
        }
      )

      console.log("  响应状态:", loginResponse.status)

      if (loginResponse.status !== 200) {
        throw new Error(`授权登录失败: ${loginResponse.status}`)
      }

      console.log("✅ Step 1 完成，服务器已准备好 Token")

      // 3. 轮询获取 AccessToken
      console.log("🔄 Step 2: 开始轮询获取 AccessToken...")
      const result = await this.pollForAccessToken(uuid, verifier)

      console.log("=== AccessToken 获取成功 ===")
      return result
    } catch (error: any) {
      console.error("❌ 获取 AccessToken 失败:")
      console.error("  错误信息:", error.message)
      if (error.response) {
        console.error("  响应状态:", error.response.status)
        console.error("  响应数据:", error.response.data)
      }
      throw error
    }
  }

  /**
   * 轮询获取 AccessToken
   */
  private async pollForAccessToken(
    uuid: string,
    verifier: string,
    maxAttempts: number = 30
  ): Promise<{ accessToken: string; email?: string }> {
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        console.log(`🔍 轮询尝试 ${attempt}/${maxAttempts}...`)

        const response = await axios.get(`https://api2.cursor.sh/auth/poll`, {
          params: { uuid, verifier },
          headers: {
            Accept: "*/*",
            Origin: "https://cursor.com"
          }
        })

        if (response.data && response.data.accessToken) {
          console.log("✅ AccessToken 获取成功!")
          console.log("  AccessToken:", response.data.accessToken.substring(0, 30) + "...")
          if (response.data.email) {
            console.log("  Email:", response.data.email)
          }
          return {
            accessToken: response.data.accessToken,
            email: response.data.email
          }
        }

        // 等待 1 秒后继续
        await new Promise(resolve => setTimeout(resolve, 1000))
      } catch (error: any) {
        console.warn(`⚠️ 第 ${attempt} 次轮询出错:`, error.message)
        await new Promise(resolve => setTimeout(resolve, 1000))
      }
    }

    throw new Error("轮询超时：未能在 30 秒内获取到 AccessToken")
  }
}
